﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.XAPO;
using SynergyLib.DSP;

namespace XAudio2Controls
{
    [StructLayout(LayoutKind.Sequential)]
    public struct LimiterParams
    {
        internal float Slope { get; set; }
        internal float Release { get; set; }
        internal float Attack { get; set; }
        internal float Threshhold { get; set; }
    }
    public class LimiterEffect : AudioProcessorBase<LimiterParams>
    {
        /*
        public LimiterEffect()
        {
            RegistrationProperties = new RegistrationProperties()
            {
                Clsid = Utilities.GetGuidFromType(typeof(AudioProcessorBase<>)),
                CopyrightInfo = "Copyright",
                FriendlyName = this.ToString(),
                MaxInputBufferCount = 100,
                MaxOutputBufferCount = 100,
                MinInputBufferCount = 100,
                MinOutputBufferCount = 100,
                Flags = PropertyFlags.Default
            };           
        }     
        */
        public override void Process(BufferParameters[] inputProcessParameters, BufferParameters[] outputProcessParameters, bool isEnabled)
        {
            int frameCount = inputProcessParameters[0].ValidFrameCount;
            DataStream input = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);
            DataStream Output = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);

            float[] lefts = new float[frameCount];
            float[] rights = new float[frameCount];
            lefts[0] = 0;
            rights[0] = 0;
            for (int i = 1; i < frameCount; i++, Counter++)
            {
                lefts[i] = input.Read<float>();
                rights[i] = input.Read<float>();
                float Slope = Parameters.Slope;
                float tresh = Parameters.Threshhold;
                float rt = Parameters.Release;
                float at = Parameters.Attack;
                float fOFn = new float();
                float a = Math.Abs(lefts[i]) - (lefts[i] - lefts[i - 1]);
                if (a <= 0)
                {
                    fOFn = 1.0f;
                }
                else
                {
                    if (((lefts[i] - lefts[i - 1]) * (1 - rt) + at * a) > tresh)
                    {
                        float logstuff = (float)(Math.Log(lefts[i], 10) - Math.Log(tresh, 10));
                        fOFn = (float)Math.Pow(10, (-Slope * logstuff));
                    }
                }
                Output.Write(lefts[i] * fOFn);
                Output.Write(rights[i] * fOFn);
            }
        }
    }
}
